package com.recursivechaos.dicr;

import java.util.Random;

import com.recursivechaos.dicr.classes.DiceException;

/**
 * User: Andrew Bell Date: 11/20/13 Time: 1:37 PM
 */
public class RollerDAOImpl implements RollDAO {
	private static int MAX_ROLL = 1290;
	private int noRolls;
	private int noSides;
	private int dSpot;
	private int modVal;
	private int modLoc = -1;
	private int initRollVal = 0;
	private int finalRollVal;
	private String modText = "";
	String inputDiceString;
	private String modifier = "";

	/**
	 * This function rolls a string, but does not check for errors. Will return
	 * 0 if failure.
	 * 
	 * @param inputDiceString
	 *            Checked string to be rolled
	 * @return  int value from string rolled
	 */
	@Override
	public int rollFromCheckedString(String inputDiceString) {
		// Currently, we need to append a space to the end in order for the
		// function to determine end points.
		inputDiceString = inputDiceString.toUpperCase() + " ";

		// find the D location first
		if (inputDiceString.contains("D")) {
			dSpot = inputDiceString.indexOf("D");
		} else {
			return 0;
		}

		// find the number of rolls
		try {
			if (dSpot == 0) {
				noRolls = 1;
			} else {
				if (inputDiceString.substring(0, 1).equals("-")) {
					throw new DiceException("I can't roll negative dice!");
				}
				noRolls = Integer.parseInt(inputDiceString.substring(0, dSpot));
				if (noRolls > MAX_ROLL) {
					throw new DiceException(
							"I don't feel like rolling that many dice.");
				}
			}
		} catch (Exception e) {
			return 0;
		}

		// find modifiers, modify string
		try {
			// Check if a modifier is present
			if (inputDiceString.contains("+")) {
				modLoc = inputDiceString.indexOf("+");
			} else if (inputDiceString.contains("-")) {
				modLoc = inputDiceString.indexOf("-");
			} else if (inputDiceString.contains("X")) {
				modLoc = inputDiceString.indexOf("X");
			}
			// If a modifier is found, modify string
			if (modLoc > -1) {
				modText = inputDiceString.substring(modLoc,
						inputDiceString.indexOf(" ", modLoc));
				modVal = Integer.parseInt(modText.substring(1));
				if (modVal > MAX_ROLL) {
					throw new DiceException(
							"A bit excessive modifier eh? You think you're clever huh?");
				}
				inputDiceString = inputDiceString.substring(0, (modLoc)) + " ";
				modifier = modText.substring(0, 1);
			}
		} catch (Exception e) {
			return 0;
		}

		// get sides
		try {
			noSides = Integer.parseInt(inputDiceString.substring((dSpot + 1),
					inputDiceString.indexOf(" ")));
			if (noSides < 1) {
				throw new DiceException(
						"A dice with less than 1 side really isn't a dice, is it?");
			}
		} catch (Exception e) {
			return 0;
		}

		// roll dice
		Random randomGenerator = new Random();
		for (int i = 0; i < noRolls; i++) {
			initRollVal = initRollVal + randomGenerator.nextInt(noSides) + 1;
		}

		// modify total if necessary.
		if (modifier.equalsIgnoreCase("")) {
			finalRollVal = initRollVal;
		} else if (modifier.equalsIgnoreCase("+")) {
			finalRollVal = initRollVal + modVal;
		} else if (modifier.equalsIgnoreCase("-")) {
			finalRollVal = initRollVal - modVal;
		} else if (modifier.equalsIgnoreCase("x")) {
			finalRollVal = initRollVal * modVal;
		} else {
			return 0;
		}
		return finalRollVal;
	}

	@Override
	public int rollFromString(String inputDiceString) throws DiceException {
		// Currently, we need to append a space to the end in order for the
		// function to determine end points.
		inputDiceString = inputDiceString.toUpperCase() + " ";

		// find the D location first
		if (inputDiceString.contains("D")) {
			dSpot = inputDiceString.indexOf("D");
		} else {
			throw new DiceException(
					"I can't seem to find me the D. I want the D.");
		}

		// find the number of rolls
		try {
			if (dSpot == 0) {
				noRolls = 1;
			} else {
				if (inputDiceString.substring(0, 1).equals("-")) {
					throw new DiceException("I can't roll negative dice!");
				}
				noRolls = Integer.parseInt(inputDiceString.substring(0, dSpot));
				if (noRolls > MAX_ROLL) {
					throw new DiceException(
							"I don't feel like rolling that many dice.");
				}
			}
		} catch (Exception e) {
			throw new DiceException("Now you're trying to make up number!");
		}

		// find modifiers, modify string
		try {
			// Check if a modifier is present
			if (inputDiceString.contains("+")) {
				modLoc = inputDiceString.indexOf("+");
			} else if (inputDiceString.contains("-")) {
				modLoc = inputDiceString.indexOf("-");
			} else if (inputDiceString.contains("X")) {
				modLoc = inputDiceString.indexOf("X");
			}
			// If a modifier is found, modify string
			if (modLoc > -1) {
				modText = inputDiceString.substring(modLoc,
						inputDiceString.indexOf(" ", modLoc));
				modVal = Integer.parseInt(modText.substring(1));
				if (modVal > MAX_ROLL) {
					throw new DiceException(
							"A bit excessive modifier eh? You think you're clever huh?");
				}
				inputDiceString = inputDiceString.substring(0, (modLoc)) + " ";
				modifier = modText.substring(0, 1);
			}
		} catch (Exception e) {
			throw new DiceException("That modifier is a little unreasonable.");
		}

		// get sides
		try {
			noSides = Integer.parseInt(inputDiceString.substring((dSpot + 1),
					inputDiceString.indexOf(" ")));
			if (noSides < 1) {
				throw new DiceException(
						"A dice with less than 1 side really isn't a dice, is it?");
			}
		} catch (Exception e) {
			throw new DiceException(
					"You can't roll that kind of dice! Where did you even find that?");
		}

		// roll dice
		Random randomGenerator = new Random();
		for (int i = 0; i < noRolls; i++) {
			initRollVal = initRollVal + randomGenerator.nextInt(noSides) + 1;
		}

		// modify total if necessary.
		if (modifier.equalsIgnoreCase("")) {
			finalRollVal = initRollVal;
		} else if (modifier.equalsIgnoreCase("+")) {
			finalRollVal = initRollVal + modVal;
		} else if (modifier.equalsIgnoreCase("-")) {
			finalRollVal = initRollVal - modVal;
		} else if (modifier.equalsIgnoreCase("x")) {
			finalRollVal = initRollVal * modVal;
		} else {
			throw new DiceException("I can't math.");
		}
		return finalRollVal;
	}
}
